﻿using CKS.Core.Framework;
using CKS.PLC.Core.Cache;
using CKS.Schedule;
using FreeSql;
using Infrastructure;
using Mapster;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using ZR.Infrastructure;
using ZR.Model.Dto.Business;
using ZR.Model.Models.ProductionControl;

namespace CKS.PLC.Core.CronJob
{
    [Schedule]
    public class StatDataJob : CronJobBase
    {
        IFreeSql<MesDB> fsql;
        DateTime StatTime = DateTime.Now; //统计日期
        /// <summary>
        /// 接收数量
        /// </summary>
        public long ReceiveCount {  get; set; } 
        /// <summary>
        /// 完成数量
        /// </summary>
        public long FinishCount {  get; set; }
        /// <summary>
        /// 完成比例
        /// </summary>
        public decimal FinishRate {  get; set; }
        /// <summary>
        /// 单次时间：单位秒
        /// </summary>
         public int OnceTime {  get; set; }

        WorkPositionResponse workPositionResponse = new WorkPositionResponse();
        /// <summary>
        /// 纸板使用情况
        /// </summary>
        private List<CarboardUsageInfoDto> Usages = new List<CarboardUsageInfoDto>();

        public SafeList<CksPackagingTask> TaskOrders = new SafeList<CksPackagingTask>();

        public StatDataJob() : base("定时统计", "0/1 * * * * ?")
        {
            fsql = InternalApp.Fsql;
            
        }

        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            StatTime = DateTime.Now; //今日统计
            var startTime = StatTime.ToString("yyyy-MM-dd 00:00:00").ToDate();
            var endTime = startTime.AddDays(1).AddTicks(-1);
            try
            {
                using (var conn = fsql.Ado.MasterPool.Get().Value)
                {
                    var startTime2 = StatTime.AddDays(-60).ToString("yyyy-MM-dd 00:00:00").ToDate();
                   var taskOrders  = conn.Select<CksPackagingTask>().Where(a => a.CreatedTime.Between(startTime2, endTime))
                        .Where(a => a.TaskStatus != TaskStatusType.上传业务系统成功).ToList();
                    TaskOrders.ClearAndAddRange(taskOrders);

                    ReceiveCount = conn.Select<CksPackagingTask>().Where(a => a.CreatedTime.Between(startTime, endTime)).Count();
                    FinishCount = conn.Select<CksPackagingTask>().Where(a => a.CreatedTime.Between(startTime, endTime) && a.TaskStatus == TaskStatusType.检查面单OK).Count();
                    FinishRate = ReceiveCount == 0 ? 0 : (FinishCount.ToDecimal() / ReceiveCount.ToDecimal()).RoundTo4Places();
                    // 给任务表添加进站时间、出站时间 、耗时
                    OnceTime = conn.Select<CksPackagingTask>().Where(a => a.CreatedTime.Between(startTime, endTime) && a.Duration > 0)
                        .OrderByDescending(a => a.Id).Take(10).Min(a => a.Duration);
                    // 查询配置的纸板类型
                    var carboardTypes = conn.Select<CksCarboardType>().ToList();

                    StatUsages(startTime, endTime, conn, carboardTypes);
                    QueryWorkPostion(conn);

                }








            }
            catch (Exception)
            {

            }


            await Task.CompletedTask;
        }

        public WorkPositionResponse GetWorkPositionResponse()
        {
            lock (ServiceCommon.GetLockObj("QueryWorkPostion"))
                return workPositionResponse;
        }
        /// <summary>
        /// 查询工位最新的加工数据
        /// </summary>
        /// <param name="conn"></param>
        private void QueryWorkPostion(DbConnection conn)
        {
            lock(ServiceCommon.GetLockObj("QueryWorkPostion"))
            {
                
                //查询最新的工位任务，查询12小时内
                var dicData1 = QueryDic(conn, "MainWork01");
                workPositionResponse.Positions[0].TaskNo = dicData1?.TaskNo;
                workPositionResponse.Positions[0].Status = dicData1 == null ? 0 : ((object)dicData1.CheckResult).ToInt();
                workPositionResponse.Positions[0].OperateTime = dicData1 == null ? "" : ((DateTime)dicData1.CreatedTime).ToTimeString();

                var dicData2 = QueryDic(conn, "MainWork02");
                workPositionResponse.Positions[1].TaskNo = dicData2?.TaskNo;
                workPositionResponse.Positions[1].Status = dicData2 == null ? 0 : ((object)dicData2.CheckResult).ToInt();
                workPositionResponse.Positions[1].OperateTime = dicData2 == null ? "" : ((DateTime)dicData2.CreatedTime).ToTimeString();


                var dicData3 = QueryDic(conn, "MainWork03");
                workPositionResponse.Positions[2].TaskNo = dicData3?.TaskNo;
                workPositionResponse.Positions[2].Status = dicData3 == null ? 0 : ((object)dicData3.CheckResult).ToInt();
                workPositionResponse.Positions[2].OperateTime = dicData3 == null ? "" : ((DateTime)dicData3.CreatedTime).ToTimeString();


                var dicData4 = QueryDic(conn, "MainWork04");
                workPositionResponse.Positions[3].TaskNo = dicData4?.TaskNo;
                workPositionResponse.Positions[3].Status = dicData4 == null ? 0 : ((object)dicData4.CheckResult).ToInt();
                workPositionResponse.Positions[3].OperateTime = dicData4 == null ? "" : ((DateTime)dicData4.CreatedTime).ToTimeString();


                var dicData5 = QueryDic(conn, "MainWork05");
                workPositionResponse.Positions[4].TaskNo = dicData5?.TaskNo;
                workPositionResponse.Positions[4].Status = dicData5 == null ? 0 : ((object)dicData5.CheckResult).ToInt();
                workPositionResponse.Positions[4].OperateTime = dicData5 == null ? "" : ((DateTime)dicData5.CreatedTime).ToTimeString();

                //回调系统，需要查询当前任务最新的回调
                DateTime dateTime = DateTime.Now.AddHours(-12);
                var one = conn.Select<CksPackagingTask>()
                    .Where(a => a.CreatedTime > dateTime && a.CanUpload)
                    .OrderBy(a => a.Id).First();
                workPositionResponse.Positions[5].TaskNo = one?.TaskNo;
                workPositionResponse.Positions[5].Status =one == null ?0:  one.UploadStatus.ToInt();
                workPositionResponse.Positions[5].OperateTime = one == null ? "" : one.UploadTime == null ? "上传中" : one.UploadTime.Value.ToTimeString();

                //计算完毕各个工位的最新加工数据
                //查询1工位的测量明细数据

               var dic1 =  ((object) dicData1).Adapt<MainWork01Dto>();


                workPositionResponse.Work01 = (dic1??new MainWork01Dto());
            }
        }

        private dynamic QueryDic(DbConnection conn,string TableName)
        {
            var tableinfo = conn.Select<CksVirtualTable>().Where(a => a.TableName == TableName).First();
            var columns = conn.Select<CksVirtualColumn>().Where(a => a.TableId == tableinfo.Id).OrderBy(a => a.Sequence).ToList();
            var table = ServiceCommon.GetFreesqlTableInfo(tableinfo, columns);
            DateTime dateTime = DateTime.Now.AddHours(-12);
            var Dic = fsql.Select<dynamic>().AsType(table.Type).Where($" CreatedTime > '{dateTime.ToFullString()}' ")
            .OrderBy("Id desc").First();
            return Dic;
        }

        /// <summary>
        /// 统计纸板使用率
        /// </summary>
        /// <param name="startTime"></param>
        /// <param name="endTime"></param>
        /// <param name="conn"></param>
        /// <param name="carboardTypes"></param>
        private  void StatUsages(DateTime startTime, DateTime endTime, DbConnection conn, List<CksCarboardType> carboardTypes)
        {
            lock(ServiceCommon.GetLockObj("StatUsages"))
            {
                List<CarboardUsageInfoDto> _carboardUsages = new List<CarboardUsageInfoDto>();
                foreach (var carboardType in carboardTypes)
                {
                    //从纸板使用记录中汇总纸板利用率
                    var usageArea = conn.Select<CksCardboardPackagingUsageLog>().Where(a => a.CreatedTime.Between(startTime, endTime)
                         && a.TypeWidth == carboardType.Width).Sum(a => a.UsageArea);
                    var outputArea = conn.Select<CksCardboardPackagingUsageLog>()
                        .Where(a => a.CreatedTime.Between(startTime, endTime)
                         && a.TypeWidth == carboardType.Width).Sum(a => a.OutputArea);
                    var rate = 0.00m;
                    if (outputArea > 0)
                    {
                        rate = (usageArea / outputArea).RoundTo4Places(2);
                    }
                    _carboardUsages.Add(new CarboardUsageInfoDto()
                    {
                        TypeWidth = carboardType.Width,
                        UsageArea = usageArea,
                        OutputArea = outputArea,
                        UtilizationRate = rate
                    });
                }
                Usages = _carboardUsages;
            }


            
        }

        /// <summary>
        /// 获取纸板使用率
        /// </summary>
        /// <returns></returns>
        public List<CarboardUsageInfoDto> GetCarboardUsages()
        {
            lock (ServiceCommon.GetLockObj("StatUsages"))
                return Usages;
        }

    }
}
